package com.zhang.bingmei_incomeexpenditure.service.template;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zhang.bingmei_incomeexpenditure.entity.Utils.SecurityPlusUtils;
import com.zhang.bingmei_incomeexpenditure.entity.comCity.CommCity;
import com.zhang.bingmei_incomeexpenditure.entity.commom.DataScope;
import com.zhang.bingmei_incomeexpenditure.entity.ie.IncomeExpenditure;
import com.zhang.bingmei_incomeexpenditure.entity.ie.IncomeExpenditurePageDTO;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleResult;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleSum;
import com.zhang.bingmei_incomeexpenditure.entity.ie.selectNew.SelectDoubleVO;
import com.zhang.bingmei_incomeexpenditure.mapper.CommCityMapper;
import com.zhang.bingmei_incomeexpenditure.mapper.IncomeExpenditureMapper;
import com.zhang.bingmei_incomeexpenditure.service.CommCityService;
import com.zhang.bingmei_incomeexpenditure.service.strategy.DataScopeStrategy;
import com.zhang.bingmei_incomeexpenditure.service.factory.DataScopeStrategyFactory;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 数据查询模板类：定义查询流程骨架，差异化逻辑由子类实现
 */
@RequiredArgsConstructor
public abstract class IncomeExpenditureQueryTemplate {
    @Resource
    protected IncomeExpenditureMapper incomeExpenditureMapper;
    @Resource
    protected CommCityService commCityService;
    @Resource
    protected CommCityMapper commCityMapper;

    /**
     * 模板方法：统一查询流程
     */
    public SelectDoubleResult executeQuery(IncomeExpenditurePageDTO dto) {
        // 1. 获取数据权限策略（策略模式）
        int roleLevel = SecurityPlusUtils.getMinLevel();
        DataScopeStrategy strategy = DataScopeStrategyFactory.getStrategy(roleLevel);

        // 2. 获取区域前缀
        DataScope dataScope = strategy.getAreaPrefix();
        validateAreaPrefix(dataScope);

        // 3. 获取区域后缀
        List<String> districtSuffixList = getDistrictSuffixList(dataScope);

        // 4. 拼接完整区域编码
        List<String> fullDistrictCodes = strategy.buildFullDistrictCodes(districtSuffixList);
        validateFullDistrictCodes(fullDistrictCodes);

        // 5. 构建查询条件（抽象方法：子类实现差异化条件）
        LambdaQueryWrapper<IncomeExpenditure> queryWrapper = buildQueryWrapper(fullDistrictCodes, dto);

        // 6. 执行查询
        List<IncomeExpenditure> entities = incomeExpenditureMapper.selectList(queryWrapper);

        // 7. 数据处理（抽象方法：子类实现差异化处理）
        List<IncomeExpenditure> processedEntities = processEntities(entities);

        // 8. 转换为VO
        List<SelectDoubleVO> voList = convertToVO(processedEntities);

        // 9. 计算合计
        SelectDoubleSum sum = calculateSum(processedEntities);

        // 10. 封装结果
        return buildResult(voList, sum);
    }

    /**
     * 抽象方法：构建查询条件（子类实现）
     */
    protected abstract LambdaQueryWrapper<IncomeExpenditure> buildQueryWrapper(List<String> fullDistrictCodes, IncomeExpenditurePageDTO dto);

    /**
     * 抽象方法：数据处理（如添加城市前缀）
     */
    protected abstract List<IncomeExpenditure> processEntities(List<IncomeExpenditure> entities);

    /**
     * 抽象方法：转换为VO
     */
    protected abstract List<SelectDoubleVO> convertToVO(List<IncomeExpenditure> entities);

    /**
     * 抽象方法：计算合计
     */
    protected abstract SelectDoubleSum calculateSum(List<IncomeExpenditure> entities);

    /**
     * 校验区域前缀
     */
    private void validateAreaPrefix(DataScope dataScope) {
        if (dataScope == null || StringUtils.isBlank(dataScope.getArea())) {
            throw new RuntimeException("区域前缀为空");
        }
    }

    /**
     * 校验完整区域编码
     */
    private void validateFullDistrictCodes(List<String> fullDistrictCodes) {
        if (fullDistrictCodes.isEmpty()) {
            throw new RuntimeException("没有有效的区域编码");
        }
    }

    /**
     * 获取区域后缀列表（通用实现，可被子类重写）
     */
    protected List<String> getDistrictSuffixList(DataScope dataScope) {
        return commCityMapper.selectDistinctLevelCodeByArea(dataScope.getArea()).stream()
                .map(CommCity::getLevelCode)
                .filter(StringUtils::isNotBlank)
                .collect(Collectors.toList());
    }

    /**
     * 封装结果（通用实现）
     */
    protected SelectDoubleResult buildResult(List<SelectDoubleVO> voList, SelectDoubleSum sum) {
        SelectDoubleResult result = new SelectDoubleResult();
        result.setSelectDoubleResults(voList);
        result.setSelectDoubleSum(sum);
        return result;
    }
}